/**
 * 模板模式：定义一个操作中的算法的骨架，而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
 * 模板模式适合应用场景:
 * 1. 当只希望客户端扩展某个特定算法步骤，而不是整个算法或其结构时，可使用模板方法模式。
 * 2. 当多个类的算法除一些细微不同之外几乎完全一样时，你可使用该模式。但其后果就是，只要算法发生变化，你就可能需要修改所有的类。
 * 缺点：
 * 1. 部分客户端可能会受到算法框架的限制。
 * 2. 模板方法中的步骤越多，其维护工作就可能会越困难。
 */
#pragma once

#include <iostream>
#include <memory>

using namespace std;

namespace templatemethod
{
class Computer
{
public:
    void product() {
        installCpu();
        installRam();
        installGraphicsCard();
    }

protected:
    virtual void installCpu() = 0;
    virtual void installRam() = 0;
    virtual void installGraphicsCard() = 0;
};

class ComputerA : public Computer
{
protected:
    void installCpu() override {
        cout << "ComputerA install Inter Core i5" << endl;
    }

    void installRam() override {
        cout << "ComputerA install 2G Ram" << endl;
    }

    void installGraphicsCard() override {
        cout << "ComputerA install Gtx940 GraphicsCard" << endl;
    }
};

class ComputerB : public Computer
{
protected:
    void installCpu() override {
        cout << "ComputerB install Inter Core i7" << endl;
    }

    void installRam() override {
        cout << "ComputerB install 4G Ram" << endl;
    }

    void installGraphicsCard() override {
        cout << "ComputerB install Gtx960 GraphicsCard" << endl;
    }
};

void ClientCode() 
{
    unique_ptr<ComputerA> computerA(new ComputerA);
    unique_ptr<ComputerB> computerB(new ComputerB);
    computerA->product();
    computerB->product();
}
}   // namespace templatemethod